#include <iostream>
#include <math.h>

// 现金收费抽象类
class CashSuper {
    public:
    virtual double acceptCash(double money) {
        return 0.0;
    }
};

// 正常收费子类
class CashNormal : public CashSuper{
    public:
    double acceptCash(double money) {
        return money;
    }
};

// 打折收费子类
class CashRebate : public CashSuper {
    public:
    CashRebate(double money_rebate):money_rebate_(money_rebate) {}
    double acceptCash(double money) {
        return money * money_rebate_;
    }
    private:
    double money_rebate_;
};

// 返利收费子类
class CashReturn : public CashSuper {
    public:
    CashReturn(double money_condition,double money_return): money_condition_(money_condition),
                                                            money_return_(money_return){}
    double acceptCash(double money) {
        double result = money;
        if(money >= money_condition_) {
            result = money - floor(money / money_condition_) * money_return_;
        }
        return result;
    }
    private:
    double money_condition_;
    double money_return_;
};

// 上下文类
class CashContext {
    public:
    CashContext(char type) {
        if(type == 'A') {
            cs_ = new CashNormal();
        }
        else if(type == 'B') {
            cs_ = new CashRebate(0.8);
        }
        else if(type == 'C'){
            cs_ = new CashReturn(300,100);
        }
    }
    ~CashContext() {
        if(cs_ != nullptr) {
            delete cs_;
            cs_ = nullptr;
        }
    }
    double GetResult(double money) {
        return cs_->acceptCash(money);
    }
    private:
    CashSuper* cs_;
    
};

int main() {
    char type;
    double money;
    std::cout << "hello strategy pattern!" << std::endl;
    std::cout << "How much?" << std::endl;
    std::cin >> money;
    std::cout << "Please input your cash strategy type:" << std::endl;
    std::cout << "A:正常收费模式 " << "B:打折模式 " << "C:返现模式  ";
    std::cin >> type;
    CashContext CC(type);
    double result_cash = CC.GetResult(money);
    std::cout << "实际收费：" << result_cash << std::endl;
    return 0;
}